/*
 * File:		rtc_comp.c
 * Purpose:		translate ppm to correction factors
 *
 */

#ifdef KL36_ENV
#include "hw_hal.h"
#else
#include "drivers.h"
#include "hal.h"
#endif

extern const uint16 temp_adc_max;
extern const uint16 temp_adc_min;
extern const uint16 adc_temp_ary[];
extern const uint16 rtc_comp[];

extern int get_temp(uint16 adc_temp);

int32 cal_ppm(double diff);
int8 cal_rtc(int32 ppm, uint8 *pfrac);

/*
diff: 1 day delta seconds. Read from meter calibration device.
translate diff to PPM.
*/
int32 cal_ppm(double diff)
{
	int32 val;

	val = (int32)(diff * 1000000 / 24 / 3600);

	return val;
}

/*
according to diff, cal the int, frac values.
input: 
	diff: 1 day delta seconds. Read from meter calibration device.
output:
	(integer, frac)

	IRTC_UpdateFineCompVal(integer, frac)
	
*/
int8 cal_rtc_ext(double diff, uint8 *pfrac)
{	
	int32 ppm;

	ppm = cal_ppm(diff);
	
	return cal_rtc(ppm, pfrac);	
}

/*
	translate the ppm to (int, frac) values.
input: 
	ppm
output:
	(int_part, frac)
	IRTC_UpdateFineCompVal(int_part, frac)
*/
int8 cal_rtc(int32 ppm, uint8 *pfrac)
{
	int int_part;
	uint8 frac, int_abs, left;
	uint32 ppm_abs;

	int_part = (ppm << 15) / 1000000;
	
	if (ppm < 0) {
		int_part -= 1;
		int_abs = 0 - int_part;
		ppm_abs = 0 - ppm;
	} else {
		int_part += 1;
		int_abs = int_part;
		ppm_abs = ppm;
	}
	
	left = ((1000000 * int_abs) >> 15) - ppm_abs;
	frac = (left << 22) / 1000000;
	if (ppm > 0) {
		int_part -= 1;
		frac = 128 - frac;	
	}
	
	*pfrac = frac;
	//printf("int=%d, frac=%d\n", int_part, frac);
	if (int_part < 0)
		int_part += 16;
	return int_part;
}

/*
 * get temp by adc value from temperature sensor
 *  adc < temp_adc_min, temp >= 70  degree.
 *  adc > temp_adc_max, temp <= -40 degree.

 return temp *2;
 if temp is odd, it is x.5 degree;
 else 
 	temp = temp / 2;
 
 * */
int get_temp(uint16 adc_temp)
{
	uint8 i;
	uint16 val, mid1, mid2;
	int temp = 50;
	uint16 mid;

	val = adc_temp;
	if (val <= temp_adc_min) {
		temp = 140; //70c
	} else if (val >= temp_adc_max) {
		temp = -80; //-40c
	} else {
		/* (-40, 70) */
		for (i = 0; i < 110; i++) {
			if ((val >= adc_temp_ary[i]) && (val <= adc_temp_ary[i+1])) {				
				mid = (adc_temp_ary[i] + adc_temp_ary[i+1] ) >> 1;
				mid1 = (adc_temp_ary[i] + mid ) >> 1;
				mid2 = (adc_temp_ary[i+1] + mid ) >> 1;
				
				if (val <= mid1)
					temp = (70 - i) * 2;
				else if (val <= mid2)
					temp = (70 - i) * 2 - 1;
				else
					temp = (69 - i) * 2;
				break;
			}
		}
	}

	return temp;
}


